import webviews from '../../webviews.js';
import urlParser from '../../util/urlParser.js';
import places from '../../places/places.js';
import React from 'react';
import formatRelativeDate from '../../util/relativeDate.js';
import classNames from 'classnames';
import StarIcon from '@mui/icons-material/Star';
import IconButton from '@mui/material/IconButton';
import Tooltip from '@mui/material/Tooltip';
import BlockIcon from '@mui/icons-material/Block';
import DarkIcon from '@mui/icons-material/DarkMode';
import LightIcon from '@mui/icons-material/LightMode';
import StarOutlineIcon from '@mui/icons-material/StarOutline';
import PrivacyTipIcon  from '@mui/icons-material/PrivacyTip';
import ErrorIcon  from '@mui/icons-material/Error';
import ProgressBar from '../Progress.js';
import SecurityIcon from '@mui/icons-material/Security';
import CloseIcon from '@mui/icons-material/Close';
import { useDispatch } from 'react-redux';
import * as store from '../../../reducers/partsSlice';
import pp from './placesPlugin.js';
import VolumeUpIcon from '@mui/icons-material/VolumeUp';
import VolumeOffIcon from '@mui/icons-material/VolumeOff';
var results = {}; // format is {pluginName: [results]}
var URLHandlers = []; // format is {trigger, action}
var lastItemDeletion = Date.now();
var topAnswer = {
  plugin: null,
  item: null,
};
const maxTagSuggestions = 12;
export default function SearchBar(props) {
  // const dispatch=useDispatch();
  const [state, setState] = React.useState({ plugins: {}, ct: 0, top: null });
  const dispatch = useDispatch();
  var state_use = props.state;
  // console.log("SearchBar================================");
  // console.log(props);
  const ref_search_input = React.useRef(null);
  React.useEffect(() => {
    pp.initialize();
    // ssp.initialize();
    // psp.initialize(props.dispatch, props.state);
  }, [])
  const show_editor = (editingValue, showSearchbar) => {
    clearAll();
    ref_search_input.current.focus();
    if (!editingValue) {
      ref_search_input.current.select();
    }

    // show();//show searbar div

    if (editingValue) {
      SearchBar.showResults(editingValue, null);
    } else {
      SearchBar.showResults('', null);
    }
  };
  SearchBar.show_editor = show_editor;
  const onClick_audio=(e) => {
    dispatch(store.partsSlice.actions.TOGGLE_MUTE());
  }
  const onClick_star = (e) => {
    console.log("onClick_star");
    places.toggleBookmarked_url(state_use.tabs[state_use.tab_value].url, state_use.tabs[state_use.tab_value].title, (isBookmarked) => {
      dispatch(store.partsSlice.actions.CLICK_STAR(isBookmarked));
    });
  };

  const onkeyup = (e) => {
    if (e.charCode === 8) {
      SearchBar.showResults(e.target.value, e);
    }
  };

  const onkeypress = (e) => {
    // console.log("onkeypress",e)
    if (e.charCode === 13) {
      // return key pressed; update the url
      // console.log("enter");
      console.log(e.target);
      if (
        e.target.getAttribute('data-autocomplete') &&
        e.target.getAttribute('data-autocomplete').toLowerCase() ===
        e.target.value.toLowerCase()
      ) {
        // special case: if the typed input is capitalized differently from the actual URL that was autocompleted (but is otherwise the same), then we want to open the actual URL instead of what was typed.
        // see https://github.com/minbrowser/min/issues/314#issuecomment-276678613
        // console.log(e.target.getAttribute('data-autocomplete'))
        openURL(e.target.getAttribute('data-autocomplete'), e);
      } else {
        // console.log(e.target.value);
        openURL(e.target.value, e);
      }
    } else if (e.charCode === 9) {
      return;
      // tab key, do nothing - in keydown listener
    } else if (e.charCode === 16) {
      return;
      // shift key, do nothing
    } else if (e.charCode === 8) {
      return;
      // delete key is handled in keyUp
    } else {
      // show the SearchBar
      showResults(e.target.value, e);
    }

    // on keydown, if the autocomplete result doesn't change, we move the selection instead of regenerating it to avoid race conditions with typing. Adapted from https://github.com/patrickburke/jquery.inlineComplete

    var v = e.key;
    var sel = e.target.value
      .substring(e.target.selectionStart, e.target.selectionEnd)
      .indexOf(v);

    if (v && sel === 0) {
      e.target.selectionStart += 1;
      e.preventDefault();
    }
  };
  const enableBlocking = (url) => {
    if (!url) {
      return;
    }
    var domain = new URL(url).hostname;

    var setting = settings.get('filtering');
    if (!setting) {
      setting = {};
    }
    if (!setting.exceptionDomains) {
      setting.exceptionDomains = [];
    }
    setting.exceptionDomains = setting.exceptionDomains.filter(
      (d) => d.replace(/^www\./g, '') !== domain.replace(/^www\./g, '')
    );
    settings.set('filtering', setting);
    webviews.callAsync(tabs.getSelected(), 'reload');
  };
  const disableBlocking = (url) => {
    if (!url) {
      return;
    }
    var domain = new URL(url).hostname;

    var setting = settings.get('filtering');
    if (!setting) {
      setting = {};
    }
    if (!setting.exceptionDomains) {
      setting.exceptionDomains = [];
    }
    // make sure the domain isn't already an exception
    if (
      !setting.exceptionDomains.some(
        (d) => d.replace(/^www\./g, '') === domain.replace(/^www\./g, '')
      )
    ) {
      setting.exceptionDomains.push(domain);
    }
    settings.set('filtering', setting);
    webviews.callAsync(tabs.getSelected(), 'reload');
  };
  const isBlockingEnabled = (url) => {
    try {
      var domain = new URL(url).hostname;
    } catch (e) {
      return false;
    }

    var setting = settings.get('filtering');
    return (
      !setting ||
      !setting.exceptionDomains ||
      !setting.exceptionDomains.some(
        (d) => d.replace(/^www\./g, '') === domain.replace(/^www\./g, '')
      )
    );
  };
  const showMenu = (button) => {
    var url = tabs.get(tabs.getSelected()).url;
    var menu = [
      [
        {
          type: 'checkbox',
          label: l('enableBlocking'),
          checked: isBlockingEnabled(url),
          click: () => {
            if (isBlockingEnabled(url)) {
              disableBlocking(url);
            } else {
              enableBlocking(url);
            }
            update_block(tabs.getSelected());
          },
        },
      ],
      // [
      //   {
      //     label: l('appMenuReportBug'),
      //     click: () => {
      //       var newTab = tabs.add({
      //         url:
      //           'https://github.com/minbrowser/min/issues/new?title=Content%20blocking%20issue%20on%20' +
      //           encodeURIComponent(url),
      //       });
      //       window.globalArgs['browserUI'].addTab(newTab, {
      //         enterEditMode: false,
      //       });
      //     },
      //   },
      // ],
    ];
    remoteMenu.open(menu);
  };
  const clearAll = () => {
    //todo
    setState((state) => ({ ...state, top: null }));
    topAnswer = {
      plugin: null,
      item: null,
    };
    for (var p in state.plugins) {
      state.plugins[p].container = [];
    }
  };
  const reset = (pluginName) => {
    // console.log("reset ",pluginName);
    // console.log("before re=======================");
    console.log(state.plugins)
    // let ele=getContainer(pluginName)
    // ele=[];
    state.plugins[pluginName].container = [];
    // if(ele) empty(ele);
    var ta = getTopAnswer(pluginName);
    if (ta) {
      setState((state) => ({ ...state, top: null }));
      topAnswer = {
        plugin: null,
        item: null,
      };
    }
    results[pluginName] = [];
  };
  const getTopAnswer = (pluginName) => {
    if (pluginName) {
      if (topAnswer.plugin === pluginName) {
        return true;
      } else {
        return false;
      }
    } else {
      return state.top;
    }
  };
  const setTopAnswer = (pluginName, data) => {
    var item = createItem(data);
    // item.setAttribute('data-plugin', pluginName);
    setState((state) => ({ ...state, top: item }));
    topAnswer = {
      plugin: pluginName,
      item: item,
    };
    results[pluginName].push(data);
  };
  const addResult = (pluginName, data, options = {}) => {
    // console.log("addResult=======");
    // console.log(pluginName,data,options)
    if (data == undefined) {
      data = {};
    }
    if (options.allowDuplicates) {
      data.allowDuplicates = true;
    }
    if (data.url && !data.allowDuplicates) {
      // skip duplicates
      for (var plugin in results) {
        for (var i = 0; i < results[plugin].length; i++) {
          if (
            results[plugin][i].url === data.url &&
            !results[plugin][i].allowDuplicates
          ) {
            return;
          }
        }
      }
    }
    let ele = getContainer(pluginName);
    let key = ele.length;
    data.key = key;
    var item = createItem(data);
    ele.push(item);
    results[pluginName].push(data);
    setState((state) => ({ ...state, ct: state.ct + 1 }));
  };
  const createItem = (data) => {
    // console.log("createItem========");
    // console.log(data);
    let cn = classNames('searchbar-item', data.classList, {
      fakefocus: data.fakeFocus,
    });
    let style = {};
    let childs = [];
    if (data.opacity) {
      style = { opacity: data.opacity };
    }
    let key = 0;
    if (data.colorCircle) {
      // var colorCircle = document.createElement('div');
      // colorCircle.className = 'image color-circle';
      // colorCircle.style.backgroundColor = data.colorCircle;
      childs.push(
        <div
          key={key++}
          className="image color-circle"
          style={{ backgroundColor: data.colorCircle }}
        ></div>
      );
    }

    if (data.icon) {
      // var el = document.createElement('i');
      // el.className = 'i ' + data.icon;
      // item.appendChild(el);
      childs.push(<i key={key++} className={'i ' + data.icon}></i>);
    }

    if (data.title) {
      // var title = document.createElement('span');
      // title.classList.add('title');

      // if (!data.secondaryText) {
      //   title.classList.add('wide');
      // }

      // title.textContent = data.title.substring(0, 1000);

      // item.appendChild(title);
      let cn_ti = classNames('title', { wide: !data.secondaryText });
      childs.push(
        <span key={key++} className={cn_ti}>
          {data.title.substring(0, 1000)}
        </span>
      );
    }

    if (data.secondaryText) {
      // secondaryText.classList.add('secondary-text');

      // secondaryText.textContent = data.secondaryText.substring(0, 1000);

      // item.appendChild(secondaryText);
      let metadataElement = [];
      if (data.metadata) {
        let key1 = 1;
        data.metadata.forEach((str) => {
          // var metadataElement = document.createElement('span');
          // metadataElement.className = 'md-info';

          // metadataElement.textContent = str;
          metadataElement.push(
            <span key={key1++} className="md-info">
              str
            </span>
          );
          // secondaryText.insertBefore(metadataElement, secondaryText.firstChild);
        });
      }
      // var secondaryText = (
      //   <span key={key++} className="secondary-text">
      //     {metadataElement}
      //     {data.secondaryText.substring(0, 1000)}
      //   </span>
      // );
      childs.push(
        <a key={key++} href={data.url}>
          {data.secondaryText.substring(0, 1000)}
        </a>
      );
      // childs.push(secondaryText);
    }

    if (data.image) {
      var image = <img key={key++} className="image" src={data.image}></img>;
      // image.className = 'image';
      // image.src = data.image;

      // item.insertBefore(image, item.childNodes[0]);
      childs.unshift(image);
    }

    if (data.iconImage) {
      // var iconImage = document.createElement('img');
      // iconImage.className = 'icon-image';
      // iconImage.src = data.iconImage;
      // iconImage.setAttribute('aria-hidden', true);

      // item.insertBefore(iconImage, item.childNodes[0]);
      let iconImage = (
        <img
          key={key++}
          className="icon-image"
          aria-hidden={true}
          src={data.iconImage}
        ></img>
      );
      childs.unshift(iconImage);
    }

    // if (data.descriptionBlock) {
    //   // var dBlock = document.createElement('span');
    //   // dBlock.classList.add('description-block');

    //   // dBlock.textContent = data.descriptionBlock;
    //       // item.appendChild(dBlock);

    // }
    if (data.descriptionBlock) {
      if (data.attribution) {
        //two block
        var attrBlock = <span className="attribution">{data.attribution}</span>; // document.createElement('span');
        let dBlock = (
          <span key={key++} className="description-block">
            {data.descriptionBlock}
            {attrBlock}
          </span>
        );
        childs.push(dBlock);
      } else {
        //dblock
        let dBlock = (
          <span key={key++} className="description-block">
            {data.descriptionBlock}
          </span>
        );
        childs.push(dBlock);
      }
    } else {
      //ablock
      if (data.attribution) {
        var attrBlock = (
          <span key={key++} className="attribution">
            {data.attribution}
          </span>
        ); // document.createElement('span');
        childs.push(attrBlock);
      }
    }
    let item;
    if (data.url) {
      item = (
        <div
          key={data.key}
          onClick={(e) => {
            openURL(data.url, e);
          }}
          data-url={data.url}
          className={cn}
          style={style}
          tabIndex={-1}
        >
          {childs}
        </div>
      );
    } else {
      if (data.click) {
        item = (
          <div
            onClick={data.click}
            key={data.key}
            className={cn}
            style={style}
            tabIndex={-1}
          >
            {childs}
          </div>
        );
      } else {
        item = (
          <div key={data.key} className={cn} style={style} tabIndex={-1}>
            {childs}
          </div>
        );
      }
    }
    // console.log(item);
    return item;
  };

  const addHeading = (pluginName, data) => {
    console.log(pluginName, data);
    let container = getContainer(pluginName);
    let key = container.length;
    container.push(
      <h4 key={key} className="searchbar-heading">
        {data.text}
      </h4>
    );
  };
  const getContainer = (pluginName) => {
    // console.log("getContainer=========")
    // console.log(pluginName)
    // let ele=document.getElementById("plugin_"+pluginName);
    // // console.log(ele);
    // return ele;
    // for (var i = 0; i < plugins.length; i++) {
    //   if (plugins[i].name === pluginName) {
    //     return plugins[i].container;
    //   }
    // }
    return state.plugins[pluginName].container;
  };

  const register = (name, object) => {
    // add the container
    console.log('register', name);
    // var container = document.createElement('div');
    // container.classList.add('searchbar-plugin-container');
    // container.setAttribute('data-plugin', name);
    // searchbar.insertBefore(container, searchbar.childNodes[object.index + 2]);

    // plugins.push({
    //   name: name,
    //   trigger: object.trigger,
    //   showResults: object.showResults,
    //   container:[],
    // });
    state.plugins[name] = {
      name: name,
      trigger: object.trigger,
      showResults: object.showResults,
      container: [],
    };
    // forceUpdate();
    results[name] = [];
  };

  const run = (text, input, event) => {
    console.log('plugins run', text);
    for (var i in state.plugins) {
      // console.log(i,state.plugins[i]);
      try {
        if (
          state.plugins[i].showResults &&
          (!state.plugins[i].trigger ||
            state.plugins[i].trigger(text))
        ) {
          // console.log("showResults")
          state.plugins[i].showResults(text, input, event);
        } else {
          // console.log("reset")
          reset(state.plugins[i].name);
        }
      } catch (e) {
        console.error(
          'error in searchbar plugin "' + state.plugins[i].name + '":',
          e
        );
      }
    }
    // forceUpdate();
  };
  // registerURLHandler = (handler) => {
  //   URLHandlers.push(handler);
  // };

  // runURLHandlers = (text) => {
  //   console.log('runURLHandlers', text);
  //   for (var i = 0; i < URLHandlers.length; i++) {
  //     console.log(i);
  //     if (URLHandlers[i](text)) {
  //       console.log(true);
  //       return true;
  //     }
  //   }
  //   console.log(false);
  //   return false;
  // };

  const getResultCount = (pluginName) => {
    if (pluginName) {
      return results[pluginName].length;
    } else {
      var resultCount = 0;
      for (var plugin in results) {
        resultCount += results[plugin].length;
      }
      return resultCount;
    }
  };
  // openURLInBackground = (url) => {
  //   // used to open a url in the background, without leaving the searchbar
  //   // SearchBar.events.emit('url-selected', { url: url, background: true });

  //   // var i = ref_root.current.querySelector('.searchbar-item:focus');
  //   // if (i) {
  //   //   // remove the highlight from an awesomebar result item, if there is one
  //   //   i.blur();
  //   // }
  // };
  const show = () => {
    // ref_root.current.hidden = false
    dispatch(store.partsSlice.actions.SHOW_SEARCH(true))
    // associatedInput = associatedInput; // searchbar.associatedInput = associatedInput
  };
  const toggledark=()=>{
    dispatch(store.partsSlice.actions.TOGGLE_DARK())
  }
  const hide = () => {
    dispatch(store.partsSlice.actions.SHOW_SEARCH(false))
    clearAll();
  };
  const getValue = () => {
    var text = ref_search_input.current.value;
    return text.replace(
      text.substring(
        ref_search_input.current.selectionStart,
        ref_search_input.current.selectionEnd
      ),
      ''
    );
  };

  const showResults = (text, event) => {
    dispatch(store.partsSlice.actions.SHOW_SEARCH(true))
    // find the real input value, accounting for highlighted suggestions and the key that was just pressed
    // delete key doesn't behave like the others, String.fromCharCode returns an unprintable character (which has a length of one)
    //outline error here
    if (event && event.keyCode !== 8) {
      var realText =
        text.substring(0, ref_search_input.current.selectionStart) +
        event.key +
        text.substring(ref_search_input.current.selectionEnd, text.length);
    } else {
      var realText = text;
    }

    run(realText, ref_search_input.current, event);
  };
  const openURL = (url, event) => {
    props.dispatch(store.partsSlice.actions.OPEN_URL(url));
  };
  const show_history = () => {
    places.searchPlaces(
      "",
      function (results) {
        SearchBar.reset('places');
        var lastRelativeDate = ''; // used to generate headings
        results
          .sort(function (a, b) {
            // order by last visit
            return b.lastVisit - a.lastVisit;
          })
          .slice(0, 250)
          .forEach(function (result, index) {
            var thisRelativeDate = formatRelativeDate(result.lastVisit);
            if (thisRelativeDate !== lastRelativeDate) {
              SearchBar.addHeading('places', { text: thisRelativeDate });
              lastRelativeDate = thisRelativeDate;
            }
            SearchBar.addResult('places', {
              title: result.title,
              secondaryText: urlParser.getSourceURL(result.url),
              fakeFocus: index === 0,
              url: result.url,
              delete: () => {
                places.deleteHistory(result.url);
              },
              showDeleteButton: true,
            });
          });
      },
      { limit: Infinity }
    );
  }
  SearchBar.reset = reset;
  SearchBar.addResult = addResult;
  SearchBar.showResults = showResults;
  SearchBar.setTopAnswer = setTopAnswer;
  SearchBar.addHeading = addHeading;
  SearchBar.getResultCount = getResultCount;
  SearchBar.register = register;
  SearchBar.show_history = show_history;
  let progress;
  let tab = state_use.tabs[state_use.tab_value]
  console.log("searchbar_________________")
  console.log(tab)
  if (tab == null) {
    progress = null;
  } else {
    progress = (
        <ProgressBar
          status={
            tab.status //error here when offline
          }
        />
    );
  }

  let div_plugins = [];
  for (var pluginName in state.plugins) {
    let item = state.plugins[pluginName];
    div_plugins.push(
      <div
        key={item.name}
        className="searchbar-plugin-container"
        data-plugin={item.name}
      >
        {item.container}
      </div>
    );
  }
  return (
    <>
      <div
        style={{
          display: 'flex',
          width: '100%',
          height: '36px',
          overflowX: 'hidden',
          overflowY: 'hidden',
        }}
        id="tab-editor"
      >
        <IconButton
            onClick={(e) => {
              dispatch(store.partsSlice.actions.CLOSE_TAB());
            }}
          >
            <CloseIcon />
          </IconButton>
          <IconButton
            onClick={toggledark}
          >
           {
            state_use.dark?<DarkIcon />:<LightIcon />
           }
          </IconButton>
          <IconButton
            onClick={onClick_star}
            style={{ display: state_use.star_hidden ? 'none' : 'inline' }}
          >
            {state_use.filled ? <StarIcon /> : <StarOutlineIcon />}
          </IconButton>
        <IconButton
            onClick={onClick_audio}
          >
            {state_use.hasAudio ? <VolumeUpIcon />:<VolumeOffIcon />}
        </IconButton>
        <IconButton
            onClick={onClick_audio}
        >
            {state_use.muted ? <VolumeOffIcon /> : <VolumeUpIcon />}
        </IconButton>
        <IconButton>
          <PrivacyTipIcon />
        </IconButton>
        <IconButton>
          <SecurityIcon />
        </IconButton>
        <input
          style={{ flex: 1 }}
          onKeyUp={onkeyup}
          onChange={(e) => {
            dispatch(store.partsSlice.actions.INPUT_CHANGE(e.target.value));
          }}
          value={state_use.input_value}
          onKeyPress={onkeypress}
          placeholder={"searchbarPlaceholder"}
          ref={ref_search_input}
          id="tab-editor-input"
          className="mousetrap"
          spellCheck="false"
        />
        <IconButton onClick={
          ()=>{
            dispatch(store.partsSlice.actions.SHOW_ERROR(!state_use.show_error));
          }
        }>
          <ErrorIcon />
        </IconButton>
      </div>
      {progress}
      <div
        style={{ display: props.hidden ? "none" : "inline" }}
        id="searchbar"
        className="theme-background-color theme-text-color"
      >
        <div className="top-answer-area">{state.top}</div>
        {div_plugins}
      </div>
    </>
  );
}
